#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <dirent.h>
#include <time.h>

#include "bash.h"
#include "pack.h"
#include "mypthread.h"
#include "file.h"

int loop = 1;
pack *pack_head;
file_download_upload sendFiles[10],recvFiles[10];

int main()
{
	init_i();
	value *p;
	pack *r;
	char buf[100] = {0};
	char order[10];
	char key[10];
	char new_value[40];
	int pthread_loop = 1;

	p = read_pzfile();
	pack_head = (pack *)malloc(sizeof(pack));
	cpy(p,pack_head);
	
	while(1)
	{
		printf("\033[0;32;24mlinchen#\033[0m");
		memset(buf,0,sizeof(buf));
		memset(order,0,sizeof(order));
		memset(key,0,sizeof(key));
		memset(new_value,0,sizeof(new_value));
		fgets(buf,100,stdin);
		sscanf(buf,"%s %s %s",order,key,new_value);
	//	printf("%s|%s|%s\n",order,key,new_value);
		
		if(!strcmp(order,"set"))
		{
			set_value(key,new_value,p);
			printf("\033[0;32;24mlinchen#\033[0mset success!\n");
		}
		else if(!strcmp(order,"get"))
		{
			get_value(key,p);
		}
		else if(!strcmp(order,"list"))
		{
			printf("\033[0;32;24mlinchen#\033[0m----\n");
			printf("\033[0;32;24mlinchen#\033[0m%s\n",p->name);
			printf("\033[0;32;24mlinchen#\033[0m%s\n",p->gxqm);	
			printf("\033[0;32;24mlinchen#\033[0m%s\n",p->bm);	
			printf("\033[0;32;24mlinchen#\033[0m%s\n",p->dh);	
			printf("\033[0;32;24mlinchen#\033[0m%s\n",p->yx);	
			printf("\033[0;32;24mlinchen#\033[0m%s\n",p->IP);	
			printf("\033[0;32;24mlinchen#\033[0m%s\n",p->Mac);
		}
		else if(!strcmp(order,"login"))
		{
			if(pthread_loop)
			{
				pthread_t tid1,tid2;
				pthread_create(&tid1,NULL,user_login,p);
				pthread_create(&tid2,NULL,recv_value,p);
				pthread_loop = 0;
				printf("\033[0;32;24mlinchen#\033[0mlogin success\n");
			}
			else 
			{
				printf("\033[0;32;24mlinchen#\033[0malread have login\n");
			}
		}
		else if(!strcmp(order,"seeuser"))
		{
			r = pack_head->next;
			printf("\033[0;32;24mlinchen#\033[0m----\n");
			while(r)
			{
				printf("\033[0;32;24mlinchen#\033[0mname: %s\n",r->name);
				printf("\033[0;32;24mlinchen#\033[0mIP: %s\n",r->IP);
				//printf("\033[0;32;24mlinchen#\033[0m%s\n",r->username);	
				r = r->next;	
			}
		}
		else if(!strcmp(order,"reload"))
		{
			pack *tr;
			r = pack_head->next;
			while(r)
			{
				tr= r;
				r = r->next;
				free(tr);
			//	pack *tr;
			}
			pack_head->next = NULL;
			int sock = socket(AF_INET,SOCK_DGRAM,0);
			int opt = 1;
			if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&opt,sizeof(opt)))
			{
				perror("setsockopt error\n");
			}

			struct sockaddr_in addr;
			addr.sin_family = AF_INET;
			addr.sin_port = htons(2425);
			inet_pton(AF_INET,"192.168.186.255",&addr.sin_addr.s_addr);

			int len = sizeof(addr);
			int size = 0;
			memset(buf,0,sizeof(buf));
			size = PackBroadcast("1025",buf,p);
			sendto(sock,buf,size,0,(struct sockaddr *)&addr,len);

		}
		else if(!strcmp(order,"send"))
		{
			send_message(key,new_value);
		}
		else if(!strcmp(order,"sendfile"))
		{
			char buff[100];
			strcpy(buff,buf);
			pthread_t tid;
			pthread_create(&tid,NULL,send_file,buff);
		}
	
		else if(!strcmp(order,"quit"))
		{
			loop = 0;
			break;
		}
	}		
}

void *user_login(void *arg)
{
	pthread_detach(pthread_self());
	value *p;
	p = (value *)malloc(sizeof(value));
	p = (value *)arg;

	char buf[1024] = {0};
		
	int sock = socket(AF_INET,SOCK_DGRAM,0);
	int opt = 1;
	if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&opt,sizeof(opt)))
	{
		perror("setsockopt error\n");
	}

	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(2425);
	inet_pton(AF_INET,"192.168.186.255",&addr.sin_addr.s_addr);

	int len = sizeof(addr);
	int size = 0;
	while(loop)
	{
		size = PackBroadcast("1025",buf,p);

		sendto(sock,buf,size,0,(struct sockaddr *)&addr,len);
		sleep(5);
	}
	close(sock);
	return NULL;
}

void *recv_value(void *arg)
{
	pthread_detach(pthread_self());

	value *p;
	p = (value *)malloc(sizeof(value));
	p = (value *)arg;

	int sock = socket(AF_INET,SOCK_DGRAM,0);

	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(2425);
	addr.sin_addr.s_addr = INADDR_ANY;

	int opt = 1;
	setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

	if(bind(sock,(struct sockaddr *)&addr,sizeof(addr)))
	{
		perror("bind error\n");
		close(sock);
		return 0;
	}

	struct sockaddr_in caddr;
	unsigned int len = sizeof(caddr);
	char buf[1024] = {0};
	char recvbuf[1024] = {0};
	int size = 0;
	int ret;
	pack *r;
	while((ret = recvfrom(sock,recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&caddr,&len)) > 0 && loop)
	{
		r = analysis_recvbuf(ret,recvbuf);

		if(!strcmp(r->cmd,"1025"))		
		{
			if(strcmp(r->IP,"192.168.186.162"))
			{
				size = PackBroadcast("3",buf,p);
				sendto(sock,buf,size,0,(struct sockaddr *)&caddr,len);
				jiance_IP(r);
			}
		}
		else if(!strcmp(r->cmd,"3"))		
		{
			if(strcmp(r->IP,"192.168.186.162"))
			{
				jiance_IP(r);
			}
		}
		else if(!strcmp(r->cmd,"2147484046") || !strcmp(r->cmd,"487") || !strcmp(r->cmd,"2147484043"))
		{
			size = PackChat_8e_ture(buf,r);
			sendto(sock,buf,size,0,(struct sockaddr *)&caddr,len);
			if(!strcmp(r->name,"6.1.123"))
			{
				size = PackChat_8e5(buf);
				sendto(sock,buf,size,0,(struct sockaddr *)&caddr,len);
			}		
		}
		else if(!strcmp(r->cmd,"288"))
		{
			size = PackChat_8e_ture(buf,r);
			sendto(sock,buf,size,0,(struct sockaddr *)&caddr,len);

			char user_name[20],chat_content[200],*pto;
			strcpy(user_name,r->username);
			strcpy(chat_content,r->name);
			pto = strchr(chat_content,'[');
			*pto = '\0';

		//	printf("%s %s\n",user_name,chat_content);
			
			pack *chat_r;
			chat_r = pack_head->next;
			while(chat_r)
			{
				if(!strcmp(chat_r->username,user_name))
					break;
				chat_r = chat_r->next;
			}
			if(chat_r)
			{
				printf("[%s]%s:%s\n",chat_r->IP,chat_r->name,chat_content);
				write(1,"\033[0;32;24mlinchen#\033[0m",strlen("\033[0;32;24mlinchen#\033[0m"));
			}
		}
		else if(!strcmp(r->cmd,"2097440"))
		{
			size = PackChat_8e_ture(buf,r);
			sendto(sock,buf,size,0,(struct sockaddr *)&caddr,len);

			pack *rr;
			rr = (pack *)malloc(sizeof(pack));
			memcpy(rr,r,sizeof(pack));
			pthread_t tid;
			pthread_create(&tid,NULL,recv_file,r);
		}

		memset(recvbuf,0,sizeof(recvbuf));
	}

	close(sock);
	return NULL;
}

void *recv_file(void *arg)
{
	pthread_detach(pthread_self());

	pack *r;
	r = (pack *)malloc(sizeof(pack));
	r = (pack *)arg;

	int j;
	for ( j = 1;j <= 10;j++)
	{
		if (recvFiles[j].status == 0)
		{
			recvFiles[j].status = 1;
			break;
		}
	}
	char *p,*file_information;
	file_information = (char *)malloc(1024);	
	strcpy(file_information,r->bm);	
	//printf("%s\n",file_information);

	p = strchr(file_information,':');
	*p = '\0';
	strcpy(recvFiles[j].packnum,r->packnum);
	file_information = p+1;
	p = strchr(file_information,':');
	*p = '\0';
	strcpy(recvFiles[j].filename,file_information);
	file_information = p+1;
	p = strchr(file_information,':');
	*p = '\0';
	sscanf(file_information,"%lx",&recvFiles[j].fileSize);
	file_information = p+5;

	pack *file_r;
	file_r = pack_head->next;
	while(file_r)
	{
		if(!strcmp(file_r->username,r->username))
			break;
		file_r = file_r->next;
	}
	strcpy(recvFiles[j].IP,file_r->IP);

	//printf("pack:%s\n",recvFiles[j].packnum);
	//printf("fileId:%d\n",j);
	//printf("filename:%s\n",recvFiles[j].filename);
	//printf("fileSize:%lu\n",recvFiles[j].fileSize);
	//printf("ip:%s\n",recvFiles[j].IP);

	int csock = socket(AF_INET,SOCK_STREAM,0);
	struct sockaddr_in recvfile_addr;
	recvfile_addr.sin_family = AF_INET;
	recvfile_addr.sin_port = htons(2425);
	inet_pton(AF_INET,recvFiles[j].IP,&recvfile_addr.sin_addr.s_addr);
	if(connect(csock,(struct sockaddr *)&recvfile_addr,sizeof(recvfile_addr)) != 0)
	{
		printf("connect error \n");
		close(csock);
		return NULL;
	}
	printf("connect success\n");
	write(1,"\033[0;32;24mlinchen#\033[0m",strlen("\033[0;32;24mlinchen#\033[0m"));

	int size;
	char buf[1024];
	size = Packfile_96(buf,recvFiles[j]);
	send(csock,buf,size,0);

	int len;
	//int file_l = 0;
	char readbuf[1024];	
	int fd = open(recvFiles[j].filename,O_WRONLY | O_CREAT,0666);

	while((len = read(csock,readbuf,sizeof(readbuf))) > 0)
	{
		write(fd,readbuf,len);
		memset(readbuf,0,sizeof(readbuf));
	//	file_l += len;
	//	if(file_l == recvFiles[j].fileSize)
	//		break;
	}
	close(fd);
	close(csock);
	printf("%s:download success\n",recvFiles[j].filename);
	write(1,"\033[0;32;24mlinchen#\033[0m",strlen("\033[0;32;24mlinchen#\033[0m"));

	recvFiles[j].status = 0;

	return NULL;

}

void *send_file(void *arg)
{
	pthread_detach(pthread_self());
	char *buf;
	buf = (char *)malloc(100);
	buf = (char *)arg;
	char order[10];
	char key[10];
	char new_value[40];
	sscanf(buf,"%s %s %s",order,key,new_value);
	pack *file_r;
	file_r = pack_head->next;
	while(file_r)
	{
		if(!strcmp(file_r->name,key))
			break;
		file_r = file_r->next;
	}
	send_pack2097440(file_r,new_value);


	int sock = socket(AF_INET,SOCK_STREAM,0);
	struct sockaddr_in saddr;
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(2425);
	inet_pton(AF_INET,pack_head->IP,&saddr.sin_addr.s_addr);

	int opt = 1;
	setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
	if(bind(sock,(struct sockaddr *)&saddr,sizeof(saddr)))
	{
		perror("bind error\n");
		close(sock);
		return 0;
	}
	listen(sock,5);

	int csock;
	struct sockaddr_in caddr;
	unsigned int len = sizeof(caddr);
	csock = accept(sock,(struct sockaddr *)&caddr,&len);

	sleep(1);
	int fd = open(new_value,O_RDONLY);
	int ret;
	while((ret = read(fd,buf,1024)) > 0)
	{
		send(csock,buf,ret,0);
	}

	close(fd);
	close(csock);
	close(sock);
	printf("sendfile success!\n");
	write(1,"\033[0;32;24mlinchen#\033[0m",strlen("\033[0;32;24mlinchen#\033[0m"));

	return NULL;
}

int jiance_IP(pack *r)
{
	pack *p,*tp;
	p = pack_head;
	while(p)
	{
		if(!strcmp(r->IP,p->IP))
			break;
		tp = p;
		p = p->next;
	}
	if(!p)
		tp->next = r;
	else if(p)
	{
		if(strcmp(r->name,p->name))
			strcpy(p->name,r->name);
	}

	return 0;

}

int send_message(char *key,char *new_value)
{
	int sock = socket(AF_INET,SOCK_DGRAM,0);
	int opt = 1;
	if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&opt,sizeof(opt)))
	{
		perror("setsockopt error\n");
	}
	struct sockaddr_in send_addr;
	int send_len = sizeof(send_addr);
	char buf[1024];
	int size;
	pack *chat_r;
	chat_r = pack_head->next;
	while(chat_r)
	{
		if(!strcmp(chat_r->name,key))
			break;
		chat_r = chat_r->next;
	}
	if(chat_r)
	{
		send_addr.sin_family = AF_INET;
		send_addr.sin_port = htons(2425);
		inet_pton(AF_INET,chat_r->IP,&send_addr.sin_addr.s_addr);
		size = PackChat_8e6(buf);
		sendto(sock,buf,size,0,(struct sockaddr *)&send_addr,send_len);
		sleep(1);
		size = PackChat_e7(buf,chat_r);
		sendto(sock,buf,size,0,(struct sockaddr *)&send_addr,send_len);
		sleep(1);
		size = PackChat_288(buf,new_value);
		sendto(sock,buf,size,0,(struct sockaddr *)&send_addr,send_len);

	}
	return 0;
}	
